<!-- https://codepen.io/isuttell/pen/raxRaJ -->
<!DOCTYPE html>
<html lang="en" style="">

<head>

  <meta charset="UTF-8">


  <meta name="apple-mobile-web-app-title" content="CodePen">

  <link rel="shortcut icon" type="image/x-icon"
    href="https://cpwebassets.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico">

  <link rel="mask-icon" type="image/x-icon"
    href="https://cpwebassets.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg"
    color="#111">


  <title>CodePen - Mouse Orbit</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js" type="text/javascript"></script>

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">



  <style>
    @import url(https://fonts.googleapis.com/css?family=Raleway:100);

    html,
    body {
      min-height: 100%;
      height: 100%;
    }

    body {
      font-family: 'Raleway', sans-serif;
      font-weight: 100;
      color: rgba(255, 255, 255, 0.75);
    }

    #title {
      position: fixed;
      top: 10px;
      left: 10px;
      font-size: 20px;
      letter-spacing: 0.1em;
      z-index: 100;
    }

    #sub-title {
      position: fixed;
      top: 35px;
      left: 10px;
      font-size: 14px;
      letter-spacing: 0.1em;
      z-index: 100;
    }

    #canvas {
      position: absolute;
      left: 0;
      top: 0;
    }
  </style>

  <script>
    if (document.location.search.match(/type=embed/gi)) {
      window.parent.postMessage("resize", "*");
    }
  </script>

  <input type="hidden" id="_w_simile" data-inspect-config="3">

</head>

<body translate="no">
  <h1 id="title">Mouse Orbit</h1>
  <h2 id="sub-title">Ghost Particle Animation</h2>
  <div id="container">
    <canvas id="canvas" width="1501" height="521" style="width: 1501px; height: 521px;"></canvas>
  </div>

  <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
  <script id="rendered-js">
    var PI2 = Math.PI * 2;
    var HALF_PI = Math.PI / 2;

    var isTouch = ('ontouchstart' in window);
    var isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/);

    function Canvas(options) {
      options = _.clone(options || {});
      this.options = _.defaults(options, this.options);

      this.el = this.options.el;
      this.ctx = this.el.getContext('2d');

      this.dpr = window.devicePixelRatio || 1;

      this.updateDimensions();
      window.addEventListener('resize', this.updateDimensions.bind(this), false);
      this.resetTarget();

      if (isTouch) {
        // touch
        this.el.addEventListener('touchstart', this.touchMove.bind(this), false);
        this.el.addEventListener('touchmove', this.touchMove.bind(this), false);
        //   	this.el.addEventListener('touchend', this.resetTarget.bind(this), false);
      } else {
        // Mouse
        window.addEventListener('mousemove', this.mouseMove.bind(this), false);
        window.addEventListener('mouseout', this.resetTarget.bind(this), false);
      }

      this.setupParticles();

      this.loop();
    }

    Canvas.prototype.updateDimensions = function () {
      this.width = this.el.width = _.result(this.options, 'width') * this.dpr;
      this.height = this.el.height = _.result(this.options, 'height') * this.dpr;
      this.el.style.width = _.result(this.options, 'width') + 'px';
      this.el.style.height = _.result(this.options, 'height') + 'px';
    };

    // Update the orb target
    Canvas.prototype.mouseMove = function (event) {
      this.target = new Vector(event.clientX * this.dpr, event.clientY * this.dpr);
    };

    // Reset to center when we mouse out
    Canvas.prototype.resetTarget = function () {
      this.target = new Vector(this.width / 2, this.height / 2);
    };

    // Touch Eent
    Canvas.prototype.touchMove = function (event) {
      if (event.touches.length === 1) { event.preventDefault(); }

      this.target = new Vector(event.touches[0].pageX * this.dpr, event.touches[0].pageY * this.dpr);
    };

    // Defaults
    Canvas.prototype.options = {
      count: 20,
      speed: 0.5,
      width: 400,
      height: 400,
      size: 10,
      radius: 5,
      background: '29, 22, 52',
      maxDistance: 100
    };


    Canvas.prototype.setupParticles = function () {
      this.particles = [];
      var index = -1;
      var between = PI2 / this.options.count;
      while (++index < this.options.count) {
        var x;
        var y;
        var angle;
        var max = Math.max(this.width, this.height);

        angle = (index + 1) * between;

        x = Math.cos(angle) * max;
        x += this.width / 2;

        y = Math.sin(angle) * max;
        y += this.height / 2;

        var particle = new Particle({
          x: x,
          y: y,
          radius: this.options.radius,
          size: this.options.size,
          angle: angle,
          color: this.options.color
        });


        this.particles.push(particle);
      }
    };

    Canvas.prototype.findClosest = function () {
      var index = -1;
      var pointsLength = this.particles.length;

      while (++index < pointsLength) {
        var closestIndex = -1;
        this.particles[index].closest = [];

        while (++closestIndex < pointsLength) {
          var closest = this.particles[closestIndex];
          var distance = this.particles[index].position.distanceTo(closest.position);
          if (distance < this.options.maxDistance) {
            var vector = new Vector(closest.position.x, closest.position.y);
            vector.opacity = 1 - distance / this.options.maxDistance;
            vector.distance = distance;
            this.particles[index].closest.push(vector);
          }
        }
      }
    };

    Canvas.prototype.loop = function () {
      //   this.clear();
      if (isTouch || isSafari) {
        this.ghost();
      } else {
        this.ghostGradient();
      }
      if (this.options.maxDistance > 0) {
        this.findClosest();
      }
      this.draw();

      window.requestAnimationFrame(_.bind(this.loop, this));
    };

    Canvas.prototype.clear = function () {
      this.ctx.clearRect(0, 0, this.width, this.height);
    };

    Canvas.prototype.ghost = function () {
      this.ctx.globalCompositeOperation = "source-over";
      this.ctx.rect(0, 0, this.width, this.height);
      if (typeof this.options.background === 'string') {
        this.ctx.fillStyle = "rgb(" + this.options.background + ")";
      } else {
        this.ctx.fillStyle = "rgb(" + this.options.background[0] + ")";
      }

      this.ctx.fill();
    };

    Canvas.prototype.ghostGradient = function () {
      var gradient;

      if (typeof this.options.background === 'string') {
        this.ctx.fillStyle = 'rgb(' + this.options.background + ')';
      } else {
        var gradient = this.ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) / 2);

        var length = this.options.background.length;
        for (var i = 0; i < length; i++) {
          gradient.addColorStop((i + 1) / length, 'rgb(' + this.options.background[i] + ')');
        }
        this.ctx.fillStyle = gradient;
      }

      this.ctx.globalOpacity = 0.1;
      this.ctx.globalCompositeOperation = "darken";
      this.ctx.fillRect(0, 0, this.width, this.height);
    };

    // Draw
    Canvas.prototype.draw = function () {
      var index = -1;
      var length = this.particles.length;
      while (++index < length) {
        var point = this.particles[index];
        var color = point.color || this.options.color;
        point.update(this.target, index);

        this.ctx.globalAlpha = 0.3;
        this.ctx.globalCompositeOperation = "lighten";
        this.ctx.fillStyle = 'rgb(' + color + ')';
        this.ctx.beginPath();
        this.ctx.arc(point.position.x, point.position.y, point.size, 0, PI2, false);
        this.ctx.closePath();
        this.ctx.fill();

        if (this.options.maxDistance > 0) {
          this.drawLines(point, color);
        }
      }
    };

    // Draw connecting lines
    Canvas.prototype.drawLines = function (point, color) {
      color = color || this.options.color;
      var index = -1;
      var length = point.closest.length;
      this.ctx.globalAlpha = 0.2;
      this.ctx.globalCompositeOperation = "screen";
      this.ctx.lineCap = 'round';
      while (++index < length) {
        this.ctx.lineWidth = point.size * 2 * point.closest[index].opacity;
        this.ctx.strokeStyle = 'rgba(' + color + ', ' + point.closest[index].opacity + ')';
        this.ctx.beginPath();
        this.ctx.moveTo(point.position.x, point.position.y);
        this.ctx.lineTo(point.closest[index].x, point.closest[index].y);
        this.ctx.stroke();
      }
    };

    function Particle(options) {
      options = _.clone(options || {});
      this.options = _.defaults(options, this.options);

      this.position = this.shift = new Vector(this.options.x, this.options.y);

      this.speed = this.options.speed || 0.01 + Math.random() * 0.04;

      this.angle = this.options.angle || 0;

      if (this.options.color) {
        var color = this.options.color.split(',');
        var colorIndex = -1;
        while (++colorIndex < 3) {
          color[colorIndex] = Math.round(parseInt(color[colorIndex], 10) + Math.random() * 100 - 50);

          // Clamp
          color[colorIndex] = Math.min(color[colorIndex], 255);
          color[colorIndex] = Math.max(color[colorIndex], 0);
        }
        this.color = color.join(', ');
      }

      // Size
      this.options.size = this.options.size || 7;
      this.size = 1 + Math.random() * this.options.size;
      this.targetSize = this.options.targetSize || this.options.size;

      this.orbit = this.options.radius * 0.5 + this.options.radius * 0.5 * Math.random();
    }

    Particle.prototype.update = function (target, index) {
      this.angle += this.speed;

      this.shift.x += (target.x - this.shift.x) * this.speed;
      this.shift.y += (target.y - this.shift.y) * this.speed;

      this.position.x = this.shift.x + Math.cos(index + this.angle) * this.orbit;
      this.position.y = this.shift.y + Math.sin(index + this.angle) * this.orbit;

      if (!isSafari) {
        this.size += (this.targetSize - this.size) * 0.03;

        if (Math.round(this.size) === Math.round(this.targetSize)) {
          this.targetSize = 1 + Math.random() * this.options.size;
        }
      }
    };

    function Vector(x, y) {
      this.x = x || 0;
      this.y = y || 0;
    }

    Vector.prototype.distanceTo = function (vector, abs) {
      var distance = Math.sqrt(Math.pow(this.x - vector.x, 2) + Math.pow(this.y - vector.y, 2));
      return abs || false ? Math.abs(distance) : distance;
    };

    new Canvas({
      el: document.getElementById('canvas'),

      count: 25,
      speed: 0.3,
      radius: 6,
      width: function () { return window.innerWidth; },
      height: function () { return window.innerHeight; },
      size: 15,
      color: '30, 180, 1',
      maxDistance: 100,
      background: ['1, 62, 66', '1, 40, 60']
    });
//# sourceURL=pen.js
  </script>







</body>

</html>